package physic.engine;

import pong.game.objects.DinamicObject;
import pong.mathematic.Vec2;
import java.util.Vector;

public class MoveEngine// extends Thread
{
	private long 			timePassed 		= 0;
	private long 			curTime 		= 0;
	private long 			lastTime 		= 0;
	private float 			timeFraction 	= 0.0f;
	private float			widthWorld		= 0;
	private Vector<Vec2> 	constForces 	= new Vector<Vec2>();
	
	public static Vector<DinamicObject>	GameObjects	= new Vector<DinamicObject>();
	
 	public MoveEngine(float widthWorld)
	{
 		this.widthWorld = widthWorld;
		curTime = System.currentTimeMillis();
		initializeConstForces();
	}
	
	public void run()
	{
		updateTime();
		applyConstForces();
		sumForces();
		moveEnts();
	}

	private void updateTime()
	{
		lastTime = curTime;
		curTime = System.currentTimeMillis();
		timePassed = (curTime - lastTime);
		timeFraction = ((float)timePassed / 1000.0f);
	}

	private void initializeConstForces()
	{
		//constForces.add(new Vec2(0.0, GRAVITY)); // GRAVITY
	}

	private synchronized void applyConstForces()
	{
		Vec2 accel = new Vec2();
		// Find the total acceleration of all const forces.
		for (int i = 0; i < constForces.size(); i++)
			accel.add(constForces.get(i));
		// Apply the sum acceleration to each entity.
		for (int i = 0; i < GameObjects.size(); i++) {
			DinamicObject s = GameObjects.get(i);
			s.addAccel(accel);
		}
	}

	private synchronized void sumForces()
	{
		for (int i = 0; i < GameObjects.size(); i++) {
			DinamicObject s = GameObjects.get(i);
			// Get the sum of all accelerations acting on object.
			Vec2 theAccel = s.sumAccel();
			// Apply the resulting change in velocity.
			Vec2 dir = new Vec2(s.dir.x + (theAccel.x * timeFraction), 
					s.dir.y + (theAccel.y * timeFraction));

			s.updateVelocity(dir);
			// Apply drag coefficient
			s.applyDrag(1.0f - (timeFraction * s.DRAG));
		}
	}

	private synchronized void moveEnts()
	{
		for (int i = 0; i < GameObjects.size(); i++) {
			DinamicObject s = GameObjects.get(i);
			// Calculate the new x and y coords.
			s.moveEnts(timeFraction);
			s.checkWallCollisions(widthWorld);
		}
		checkCollisions();
	}

	private synchronized void checkCollisions()
	{
		for (int i = 0; i < GameObjects.size() - 1; i++) {
			DinamicObject s = GameObjects.get(i);
			Vec2 sCenter = s.getCenter();
			for (int j = i + 1; j < GameObjects.size(); j++) {
				DinamicObject t = GameObjects.get(j);
				if (t == null) break;
				Vec2 tCenter = t.getCenter();
				float distBetween = sCenter.distance(tCenter);
				//float bigR = s.radius > t.radius ? s.radius : t.radius;
				if (distBetween < (s.radius + t.radius)) 
					s.collide(t, distBetween);
			}
		}
	}
}
